package com.elephant.core.socket.socket3;

import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 * 4、设置超时时间
 * 5、接收数据乱码
 * @author hai
 * @description
 * @date 14:09 2018/8/31
 */
public class ClientForTimeout {

    public static void main(String[] args) throws IOException {

        String host = "127.0.0.1";
        Integer port = 8888;
        Socket socket = new Socket(host,port);
        Writer writer = new OutputStreamWriter(socket.getOutputStream());
        writer.write("hello world");
        writer.write("eof\n");
        writer.flush();

        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        //设置超时时间为10毫秒
        socket.setSoTimeout(10*1000);
        socket.setTcpNoDelay(false);

        /**
         * API说明：为 TCP 套接字设置 keepalive 选项时，如果在 2 个小时（注：实际值与实现有关）内在任意方向上都没有跨越套接字交换数据，则 TCP 会自动将 keepalive 探头发送到同位体。
         *
         *          解读：在两个小时之内主从双方都没有数据交换的时候，那么TCP会自己发送一个keeplive的探针看对方的状态，返回的状态有三种：
         *          1.对方有回应并返回期望的ACK，正常；
         *          2.对方有回应但是返回一个RST响应（不清楚的可以查一下RST攻击），不正常，主动关闭连接。
         *          3.对方没有响应，说明主机可能都已经关闭，自然也主动断开连接。
         */
        socket.setKeepAlive(true);

        StringBuilder sb = new StringBuilder();
        String temp;
        int index;
        try{
            while ((temp = reader.readLine()) != null){
                if((index = temp.indexOf("eof")) != -1){
                    sb.append(temp, 0 , index);
                }
                sb.append(temp);
            }
        }catch (SocketTimeoutException e){
            e.printStackTrace();
            System.out.println("数据读取超时");
        }
        System.out.println("From Server:" + sb);

        writer.close();
        reader.close();
        socket.close();
    }
}
